﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _1.ComplexNumber
{
    class ComplexNumber
    {
        private double realPart;
        private double imaginaryPart;

        public ComplexNumber(double realPart, double imaginaryPart)
        {
            this.realPart = realPart;
            this.imaginaryPart = imaginaryPart;
        }

        public double RealPart
        {
            get { return realPart; }
            set { realPart = value; }
        }

        public double ImaginaryPart
        {
            get { return imaginaryPart; }
            set { imaginaryPart = value; }
        }

        public double this[int index]
        {
            get
            {
                if (index != 0 && index != 1)
                {
                    throw new IndexOutOfRangeException("Invalid complex number index");
                }
                else
                {
                    if (index == 1)
                    {
                        return this.imaginaryPart;
                    }
                    else
                    {
                        return this.realPart;
                    }
                }
            }
        }

        public static ComplexNumber operator +(ComplexNumber firstNumber, ComplexNumber secondNumber)
        {
            double sumRealPart = firstNumber.RealPart + secondNumber.RealPart;
            double sumImaginaryPart = firstNumber.ImaginaryPart + secondNumber.ImaginaryPart;

            return new ComplexNumber(sumRealPart, sumImaginaryPart);
        }

        public static ComplexNumber operator -(ComplexNumber firstNumber, ComplexNumber secondNumber)
        {
            double subRealPart = firstNumber.RealPart - secondNumber.RealPart;
            double subImaginaryPart = firstNumber.ImaginaryPart - secondNumber.ImaginaryPart;

            return new ComplexNumber(subRealPart, subImaginaryPart);
        }

        public static ComplexNumber operator *(ComplexNumber firstNumber, ComplexNumber secondNumber)
        {
               // (a+bi) (c+di) = (ac-bd) + (bc+ad)i.\ 
            double mulRealPart = firstNumber.RealPart * secondNumber.RealPart -
                firstNumber.ImaginaryPart * secondNumber.ImaginaryPart;
            double mulImaginaryPart = firstNumber.ImaginaryPart * secondNumber.RealPart +
                firstNumber.RealPart * secondNumber.ImaginaryPart;

            return new ComplexNumber(mulRealPart, mulImaginaryPart);
        }

        public static ComplexNumber operator /(ComplexNumber firstNumber, ComplexNumber secondNumber)
        {
            double divisor = secondNumber.RealPart * secondNumber.RealPart + 
                secondNumber.ImaginaryPart * secondNumber.imaginaryPart;

            double divRealPart = (firstNumber.RealPart * secondNumber.RealPart +
                firstNumber.ImaginaryPart * secondNumber.ImaginaryPart ) / divisor;

            double divImaginaryPart = (firstNumber.ImaginaryPart * secondNumber.RealPart -
                firstNumber.RealPart * secondNumber.ImaginaryPart) / divisor;
            
            return new ComplexNumber(divRealPart, divImaginaryPart);
        }

        public static implicit operator double(ComplexNumber number)
        {
            double absoluteValue = Math.Sqrt(number.RealPart * number.RealPart +
                number.ImaginaryPart * number.ImaginaryPart);

            return absoluteValue;
        }

        public static explicit operator ComplexNumber(double number)
        {
            return new ComplexNumber(number, 0);
        }

        public override string ToString()
        {
            string messageToOutput = string.Format ("{0} + {1}* i", this.realPart, this.imaginaryPart);
            return messageToOutput;
        }
    }
}
